package com.uzai.console.service.report.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.converters.longconverter.LongStringConverter;
import com.alibaba.excel.util.StringUtils;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.uzai.common.enums.DeviceTypeEnum;
import com.uzai.common.exception.BusinessException;
import com.uzai.common.result.ResponseCode;
import com.uzai.common.utils.Math;
import com.uzai.console.common.ResponseMsg;
import com.uzai.console.common.UzaiRespVo;
import com.uzai.console.common.utils.DateUtil;
import com.uzai.console.common.utils.Tools;
import com.uzai.console.common.utils.ZipUtils;
import com.uzai.console.config.UzaiConsoleSysConfig;
import com.uzai.console.constant.CacheKey;
import com.uzai.console.constant.Const;
import com.uzai.console.dto.feign.report.OrderRevenueReportFeignDto;
import com.uzai.console.dto.report.OrderRevenueReportExportResultDto;
import com.uzai.console.dto.report.OrderRevenueReportQuery;
import com.uzai.console.dto.report.OrderRevenueIndicatorDto;
import com.uzai.console.dto.report.OrderRevenueReportQuery;
import com.uzai.console.dto.wechatprivate.devicewechatinfo.DeviceWechatInfoQuery;
import com.uzai.console.dto.wechatwork.devicewxworkinfo.DeviceWxworkInfoQuery;
import com.uzai.console.dto.wxpubmanage.WxpubInfoListQuery;
import com.uzai.console.entity.DeviceWechatInfo;
import com.uzai.console.entity.DeviceWxworkInfo;
import com.uzai.console.entity.Merchant;
import com.uzai.console.entity.wxpubmanage.WxpubInfoEntity;
import com.uzai.console.enums.ExportInfoTypeEnum;
import com.uzai.console.enums.SmsType;
import com.uzai.console.mapper.*;
import com.uzai.console.mapper.stats.OrderProfitStatsMapper;
import com.uzai.console.service.device.DeviceService;
import com.uzai.console.service.exportinfo.ExportInfoService;
import com.uzai.console.service.feign.UzaiReportServerFeignService;
import com.uzai.console.service.report.OrderRevenueReportService;
import com.uzai.console.vo.exportinfo.ExportAmountVo;
import com.uzai.console.vo.feign.report.OrderRevenueIndicatorReportFeignVo;
import com.uzai.console.vo.feign.report.OrderRevenueReportFeignVo;
import com.uzai.console.vo.report.OrderRevenueReportExport;
import com.uzai.console.vo.report.OrderRevenueReportVo;
import com.uzai.console.vo.report.OrderRevenueIndicatorReportVo;
import com.uzai.console.vo.report.OrderRevenueReportVo;
import org.apache.tools.zip.ZipOutputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 订单收益报表
 * @author liuqi
 * @date 2021年08月25日 20:18
 */
@Service
public class OrderRevenueReportServiceImpl implements OrderRevenueReportService {

    private Logger logger = LoggerFactory.getLogger(OrderRevenueReportServiceImpl.class);

    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private OrderProfitStatsMapper orderProfitStatsMapper;
    @Autowired
    private DeviceWechatInfoMapper deviceWechatInfoMapper;
    @Autowired
    private DeviceWxworkInfoMapper deviceWxworkInfoMapper;
    @Autowired
    private WxpubInfoMapper wxpubInfoMapper;
    @Autowired
    private UzaiReportServerFeignService uzaiReportServerFeignService;
    @Autowired
    private DeviceService deviceService;
    @Autowired
    private SysConfigMapper sysConfigMapper;
    @Autowired
    private MerchantMapper merchantMapper;
    @Autowired
    private UzaiConsoleSysConfig uzaiConsoleSysConfig;
    @Autowired
    private ExportInfoService exportInfoService;

    /**
     * 订单收益报表
     * @author liuqi
     * @date 2021/8/25 11:38
     * @param orderRevenueReportQuery
     * @return null
     */
    public Page<OrderRevenueReportVo> orderRevenueReport(OrderRevenueReportQuery orderRevenueReportQuery){

        //返回到页面分页对象
        Page<OrderRevenueReportVo> pageVo = new Page<>();
        orderRevenueReportQuery.convert(pageVo);
        //新建返回到页面的LIST对象
        List<OrderRevenueReportVo> orderRevenueReportVoList = new ArrayList<>();

        Long merId = orderRevenueReportQuery.getMerId();
        String deviceType = orderRevenueReportQuery.getDeviceType();
        //机器人查询条件
        List<Long> deviceUniqueIdList = orderRevenueReportQuery.getDeviceUniqueIdList();
        //查询开始时间
        Integer queryStartTime = orderRevenueReportQuery.getQueryStartTime();
        //查询结束时间
        Integer queryEndTime = orderRevenueReportQuery.getQueryEndTime();
        //查询平台（默认查询全部）
        Integer platformType = Tools.getInteger(orderRevenueReportQuery.getPlatformType());

        //判断查询条件
        if(merId == null){
            throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "系统参数错误");
        }

        if(StringUtils.isBlank(deviceType)){
            throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "请选择设备类型");
        }

        if(queryStartTime == null){
            throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "请输入时间范围");
        }

        if(queryEndTime == null){
            throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "请输入时间范围");
        }

        int now = DateUtil.getNowTime();

        if(queryEndTime.intValue() < queryStartTime.intValue()){
            throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "结束时间不能早于开始时间");
        }

        if(queryEndTime.intValue()- queryStartTime.intValue() > 31*24*3600){
            throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "最多只能查询31天的报表");
        }

        if(now - queryStartTime.intValue() > 90*24*3600){
            throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "最早只能查询90天以内的报表");
        }

        //手动处理机器人分页查询-如果是机器人昵称，则按照中文gbk排序
        List<OrderItem> orderItemList = orderRevenueReportQuery.getOrderItemList();
        if(orderItemList != null && orderItemList.size() > 0){
            for (OrderItem orderItem :orderItemList){
                if("device_name".equals(orderItem.getColumn())){
                    orderItem.setColumn(" convert( " + orderItem.getColumn() + " using gbk) ");
                }
            }
        }

        //个人微信
        if(DeviceTypeEnum.DT_PC_WECHAT.getKey().equals(deviceType)){
            Page<DeviceWechatInfo> page = new Page<>();
            orderRevenueReportQuery.convert(page);
            DeviceWechatInfoQuery deviceWechatInfoQuery = new DeviceWechatInfoQuery();
            BeanUtils.copyProperties(orderRevenueReportQuery, deviceWechatInfoQuery);
            deviceWechatInfoQuery.setIdList(orderRevenueReportQuery.getDeviceUniqueIdList());
            deviceWechatInfoQuery.setMerId(merId);
            ArrayList<DeviceWechatInfo> deviceWechatInfoList =  deviceWechatInfoMapper.findByList(page, deviceWechatInfoQuery);
            BeanUtils.copyProperties(page, pageVo);
            if(deviceWechatInfoList != null && deviceWechatInfoList.size() > 0){
                for (DeviceWechatInfo deviceWechatInfo : deviceWechatInfoList){


                    OrderRevenueReportVo orderRevenueReportVo = new OrderRevenueReportVo();
                    orderRevenueReportVo.setDeviceUniqueId(deviceWechatInfo.getId());
                    orderRevenueReportVo.setDeviceName(deviceWechatInfo.getDeviceName());
                    orderRevenueReportVo.setDeviceRemark(deviceWechatInfo.getDeviceRemark());
                    orderRevenueReportVo.setHeadImgUrl(deviceWechatInfo.getHeadImgUrl());
                    orderRevenueReportVoList.add(orderRevenueReportVo);
                }
            }
        }else if(DeviceTypeEnum.DT_WORK_WECHAT.getKey().equals(deviceType)){
            Page<DeviceWxworkInfo> page = new Page<>();
            orderRevenueReportQuery.convert(page);
            DeviceWxworkInfoQuery deviceWxworkInfoQuery = new DeviceWxworkInfoQuery();
            BeanUtils.copyProperties(orderRevenueReportQuery, deviceWxworkInfoQuery);
            deviceWxworkInfoQuery.setIdList(orderRevenueReportQuery.getDeviceUniqueIdList());
            deviceWxworkInfoQuery.setMerId(merId);
            ArrayList<DeviceWxworkInfo> deviceWxworkInfoList =  deviceWxworkInfoMapper.findByList(page, deviceWxworkInfoQuery);
            BeanUtils.copyProperties(page, pageVo);
            if(deviceWxworkInfoList != null && deviceWxworkInfoList.size() > 0){
                for (DeviceWxworkInfo deviceWxworkInfo : deviceWxworkInfoList){
                    OrderRevenueReportVo orderRevenueReportVo = new OrderRevenueReportVo();
                    orderRevenueReportVo.setDeviceUniqueId(deviceWxworkInfo.getId());
                    orderRevenueReportVo.setDeviceName(deviceWxworkInfo.getDeviceName());
                    orderRevenueReportVo.setDeviceRemark(deviceWxworkInfo.getDeviceRemark());
                    orderRevenueReportVo.setHeadImgUrl(deviceWxworkInfo.getHeadImgUrl());
                    orderRevenueReportVoList.add(orderRevenueReportVo);
                }
            }
        }else if(DeviceTypeEnum.WX_PUB.getKey().equals(deviceType)){
            Page<WxpubInfoEntity> page = new Page<>();
            orderRevenueReportQuery.convert(page);
            WxpubInfoListQuery wxpubInfoListQuery = new WxpubInfoListQuery();
            BeanUtils.copyProperties(orderRevenueReportQuery, wxpubInfoListQuery);
            wxpubInfoListQuery.setIdList(orderRevenueReportQuery.getDeviceUniqueIdList());
            wxpubInfoListQuery.setMerId(merId);
            List<WxpubInfoEntity> wxpubInfoEntityList =  wxpubInfoMapper.queryList(page, wxpubInfoListQuery);
            BeanUtils.copyProperties(page, pageVo);
            if(wxpubInfoEntityList != null && wxpubInfoEntityList.size() > 0){
                for (WxpubInfoEntity wxpubInfoEntity : wxpubInfoEntityList){
                    OrderRevenueReportVo orderRevenueReportVo = new OrderRevenueReportVo();
                    orderRevenueReportVo.setDeviceUniqueId(wxpubInfoEntity.getId());
                    orderRevenueReportVo.setDeviceName(wxpubInfoEntity.getDeviceName());
                    orderRevenueReportVo.setDeviceRemark(wxpubInfoEntity.getDeviceRemark());
                    orderRevenueReportVo.setHeadImgUrl(wxpubInfoEntity.getHeadImgUrl());
                    orderRevenueReportVoList.add(orderRevenueReportVo);
                }
            }
        }

        //有机器人才去查询
        if(orderRevenueReportVoList != null && orderRevenueReportVoList.size() > 0){

            //封装微服务机器人参数
            List<Long> robotIds = new ArrayList<>();
            for(OrderRevenueReportVo orderRevenueReportVo : orderRevenueReportVoList){
                //子账号负责的机器人列表
                List<Long> subDeviceUniqueIdList = orderRevenueReportQuery.getSubDeviceUniqueIdList();
                if(subDeviceUniqueIdList != null && subDeviceUniqueIdList.size() > 0){
                    for (Long subDeviceUniqueId : subDeviceUniqueIdList){
                        if(subDeviceUniqueId.longValue() == orderRevenueReportVo.getDeviceUniqueId().longValue()){
                            robotIds.add(orderRevenueReportVo.getDeviceUniqueId());
                        }
                    }
                }else{
                    robotIds.add(orderRevenueReportVo.getDeviceUniqueId());
                }
            }

            OrderRevenueReportFeignDto orderRevenueReportFeignDto = new OrderRevenueReportFeignDto();
            orderRevenueReportFeignDto.setStartTime(queryStartTime);
            orderRevenueReportFeignDto.setEndTime(queryEndTime);
            orderRevenueReportFeignDto.setRobotIds(robotIds);
            orderRevenueReportFeignDto.setPlatformType(platformType);
            orderRevenueReportFeignDto.setMerId(merId);
            orderRevenueReportFeignDto.setDeviceType(DeviceTypeEnum.getByKey(deviceType).getId());
            UzaiRespVo<List<OrderRevenueReportFeignVo>> uzaiRespVo =  uzaiReportServerFeignService.orderRevenueSearch(orderRevenueReportFeignDto);
            //logger.info("----调用订单收益分页报表微服务---para={}, result={}", JSONObject.toJSONString(orderRevenueReportFeignDto), JSONObject.toJSONString(uzaiRespVo));
            if(uzaiRespVo != null && uzaiRespVo.getCode() == 200){
                List<OrderRevenueReportFeignVo> orderRevenueReportFeignVoList = uzaiRespVo.getData();
                if(orderRevenueReportFeignVoList != null && orderRevenueReportFeignVoList.size() > 0){
                    for (OrderRevenueReportFeignVo orderRevenueReportFeignVo : orderRevenueReportFeignVoList){
                        for (OrderRevenueReportVo orderRevenueReportVo : orderRevenueReportVoList){
                            //匹配查找返回列表中的对象
                            if(orderRevenueReportVo.getDeviceUniqueId().longValue() == orderRevenueReportFeignVo.getRobotId().longValue()){
                                //对象赋值
                                BeanUtils.copyProperties(orderRevenueReportFeignVo, orderRevenueReportVo);
                                break;
                            }
                        }
                    }
                }
            }
        }

        pageVo.setRecords(orderRevenueReportVoList);
        //将分页信息复制到返回到页面的分页MO当中
        return pageVo;
    }


    /**
     * 订单收益指标查询
     * @author liuqi
     * @date 2021/8/25 11:38
     * @param orderRevenueIndicatorDto
     * @return null
     */
    public OrderRevenueIndicatorReportVo orderRevenueIndicator(OrderRevenueIndicatorDto orderRevenueIndicatorDto){

        //是否页面选择了机器人-如果页面选择了机器人-则总预估佣金、总预估利润、有效订单笔数 取绑定绑定机器人数值
        boolean bandedDeviceFlag = false;

        //返回到页面结果
        OrderRevenueIndicatorReportVo orderRevenueIndicatorReportVo = new OrderRevenueIndicatorReportVo();

        Long merId = orderRevenueIndicatorDto.getMerId();
        String deviceType = orderRevenueIndicatorDto.getDeviceType();
        //机器人查询条件
        List<Long> deviceUniqueIdList = orderRevenueIndicatorDto.getDeviceUniqueIdList();
        //查询机器人不为空，则绑定了机器人
        if(deviceUniqueIdList != null && deviceUniqueIdList.size() > 0){
            bandedDeviceFlag = true;
        }

        //查询开始时间
        Integer queryStartTime = orderRevenueIndicatorDto.getQueryStartTime();
        //查询结束时间
        Integer queryEndTime = orderRevenueIndicatorDto.getQueryEndTime();
        //查询平台（默认查询全部）
        Integer platformType = Tools.getInteger(orderRevenueIndicatorDto.getPlatformType());
        //判断查询条件
        if(merId == null){
            throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "系统参数错误");
        }

        if(StringUtils.isBlank(deviceType)){
            throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "请选择设备类型");
        }

        if(queryStartTime == null){
            throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "请输入时间范围");
        }

        if(queryEndTime == null){
            throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "请输入时间范围");
        }

        int now = DateUtil.getNowTime();

        if(queryEndTime.intValue() < queryStartTime.intValue()){
            throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "结束时间不能早于开始时间");
        }

        if(queryEndTime.intValue()- queryStartTime.intValue() > 31*24*3600){
            throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "最多只能查询31天的报表");
        }

        if(now - queryStartTime.intValue() > 90*24*3600){
            throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "最早只能查询90天以内的报表");
        }

        //新建返回到页面的LIST对象
        //封装微服务机器人参数
        List<Long> robotIds = new ArrayList<>();

        //个人微信
        if(DeviceTypeEnum.DT_PC_WECHAT.getKey().equals(deviceType)){
            DeviceWechatInfoQuery deviceWechatInfoQuery = new DeviceWechatInfoQuery();
            BeanUtils.copyProperties(orderRevenueIndicatorDto, deviceWechatInfoQuery);
            deviceWechatInfoQuery.setIdList(deviceUniqueIdList);
            deviceWechatInfoQuery.setMerId(merId);
            ArrayList<DeviceWechatInfo> deviceWechatInfoList =  deviceWechatInfoMapper.findByList(deviceWechatInfoQuery);
            if(deviceWechatInfoList != null && deviceWechatInfoList.size() > 0){
                for (DeviceWechatInfo deviceWechatInfo : deviceWechatInfoList){
                    robotIds.add(deviceWechatInfo.getId());
                }
            }
        }else if(DeviceTypeEnum.DT_WORK_WECHAT.getKey().equals(deviceType)){
            Page<DeviceWxworkInfo> page = new Page<>();
            DeviceWxworkInfoQuery deviceWxworkInfoQuery = new DeviceWxworkInfoQuery();
            BeanUtils.copyProperties(orderRevenueIndicatorDto, deviceWxworkInfoQuery);
            deviceWxworkInfoQuery.setIdList(deviceUniqueIdList);
            deviceWxworkInfoQuery.setMerId(merId);
            ArrayList<DeviceWxworkInfo> deviceWxworkInfoList =  deviceWxworkInfoMapper.findByList(deviceWxworkInfoQuery);
            if(deviceWxworkInfoList != null && deviceWxworkInfoList.size() > 0){
                for (DeviceWxworkInfo deviceWxworkInfo : deviceWxworkInfoList){
                    robotIds.add(deviceWxworkInfo.getId());
                }
            }
        }else if(DeviceTypeEnum.WX_PUB.getKey().equals(deviceType)){
            WxpubInfoListQuery wxpubInfoListQuery = new WxpubInfoListQuery();
            BeanUtils.copyProperties(orderRevenueIndicatorDto, wxpubInfoListQuery);
            wxpubInfoListQuery.setIdList(deviceUniqueIdList);
            wxpubInfoListQuery.setMerId(merId);
            List<WxpubInfoEntity> wxpubInfoEntityList =  wxpubInfoMapper.queryList(wxpubInfoListQuery);
            if(wxpubInfoEntityList != null && wxpubInfoEntityList.size() > 0){
                for (WxpubInfoEntity wxpubInfoEntity : wxpubInfoEntityList){
                    robotIds.add(wxpubInfoEntity.getId());
                }
            }
        }

        //有机器人才去查询
        if(robotIds != null && robotIds.size() > 0){

            //封装微服务机器人参数
            List<Long> robotIds_new = new ArrayList<>();
            for(Long deviceUniqueId : robotIds){
                //子账号负责的机器人列表
                List<Long> subDeviceUniqueIdList = orderRevenueIndicatorDto.getSubDeviceUniqueIdList();
                if(subDeviceUniqueIdList != null && subDeviceUniqueIdList.size() > 0){
                    //子账号绑定了机器人
                    bandedDeviceFlag = true;
                    for (Long subDeviceUniqueId : subDeviceUniqueIdList){
                        if(subDeviceUniqueId.longValue() == deviceUniqueId.longValue()){
                            robotIds_new.add(deviceUniqueId);
                        }
                    }
                }else{
                    robotIds_new.add(deviceUniqueId);
                }
            }

            OrderRevenueReportFeignDto orderRevenueReportFeignDto = new OrderRevenueReportFeignDto();
            orderRevenueReportFeignDto.setStartTime(queryStartTime);
            orderRevenueReportFeignDto.setEndTime(queryEndTime);
            //判断是否绑定机器人
            if(bandedDeviceFlag){//绑定机器人才传送机器人列表参数
                orderRevenueReportFeignDto.setRobotIds(robotIds_new);
            }
            orderRevenueReportFeignDto.setPlatformType(platformType);
            orderRevenueReportFeignDto.setMerId(merId);
            orderRevenueReportFeignDto.setDeviceType(DeviceTypeEnum.getByKey(deviceType).getId());
            UzaiRespVo<OrderRevenueIndicatorReportFeignVo> uzaiRespVo =  uzaiReportServerFeignService.orderRevenueIndicatorSerach(orderRevenueReportFeignDto);
            //logger.info("----调用订单收益指标微服务---para={}, result={}", JSONObject.toJSONString(orderRevenueReportFeignDto), JSONObject.toJSONString(uzaiRespVo));
            if(uzaiRespVo != null && uzaiRespVo.getCode() == 200){
                OrderRevenueIndicatorReportFeignVo orderRevenueIndicatorReportFeignVo = uzaiRespVo.getData();
                if(orderRevenueIndicatorReportFeignVo != null){
                    //对象赋值
                    BeanUtils.copyProperties(orderRevenueIndicatorReportFeignVo, orderRevenueIndicatorReportVo);

                    //有效订单预估总佣金
                    Double totalEstimateCommission = Tools.getDouble(orderRevenueIndicatorReportVo.getTotalEstimateCommission());
                    //有效订单预估总利润
                    Double totalEstimateProfit = Tools.getDouble(orderRevenueIndicatorReportVo.getTotalEstimateProfit());
                    if(totalEstimateCommission.doubleValue() != 0.00){
                        //有效订单预估利润占比 = 有效订单预估总利润/有效订单预估总佣金
                        Double rateEstimateProfit = Math.mul(Math.div(totalEstimateProfit, totalEstimateCommission, 4), 100);
                        orderRevenueIndicatorReportVo.setRateEstimateProfit(rateEstimateProfit);
                    }else{
                        orderRevenueIndicatorReportVo.setRateEstimateProfit(0.00d);
                    }

                    //总分拥
                    Double totalDividendCount = Tools.getDouble(orderRevenueIndicatorReportVo.getTotalDividendCount());
                    //已绑定买家的总预估佣金
                    Double bindTotalEstimateCommission = Tools.getDouble(orderRevenueIndicatorReportVo.getBindTotalEstimateCommission());
                    if(totalDividendCount.doubleValue() != 0.00){
                        //有效订单预估利润占比 = 有效订单预估总利润/有效订单预估总佣金
                        Double rateDividendCount = Math.mul(Math.div(totalDividendCount, bindTotalEstimateCommission, 4), 100);
                        orderRevenueIndicatorReportVo.setRateDividendCount(rateDividendCount);
                    }else{
                        orderRevenueIndicatorReportVo.setRateDividendCount(0.00d);
                    }


                }
            }
        }

        return orderRevenueIndicatorReportVo;
    }

    /**
     * 订单收益查询结果导出文件前检验接口
     * @author liuqi
     * @date 2021/8/25 11:38
     * @param orderRevenueReportQuery
     */
    public ExportAmountVo getExportAmount(OrderRevenueReportQuery orderRevenueReportQuery){

        //执行分页查询对象
        //返回到页面分页对象
        Page<OrderRevenueReportVo> pageVo = new Page<>();
        orderRevenueReportQuery.convert(pageVo);
        //新建返回到页面的LIST对象
        List<OrderRevenueReportVo> orderRevenueReportVoList = new ArrayList<>();

        Long merId = orderRevenueReportQuery.getMerId();
        String deviceType = orderRevenueReportQuery.getDeviceType();
        //机器人查询条件
        List<Long> deviceUniqueIdList = orderRevenueReportQuery.getDeviceUniqueIdList();
        //查询开始时间
        Integer queryStartTime = orderRevenueReportQuery.getQueryStartTime();
        //查询结束时间
        Integer queryEndTime = orderRevenueReportQuery.getQueryEndTime();

        //判断查询条件
        if(merId == null){
            throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "系统参数错误");
        }

        if(StringUtils.isBlank(deviceType)){
            throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "请选择设备类型");
        }

        if(queryStartTime == null){
            throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "请输入时间范围");
        }

        if(queryEndTime == null){
            throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "请输入时间范围");
        }

        int now = DateUtil.getNowTime();

        if(queryEndTime.intValue() < queryStartTime.intValue()){
            throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "结束时间不能早于开始时间");
        }

        if(queryEndTime.intValue()- queryStartTime.intValue() > 31*24*3600){
            throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "最多只能查询31天的报表");
        }

        if(now - queryStartTime.intValue() > 90*24*3600){
            throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "最早只能查询90天以内的报表");
        }

        //手动处理机器人分页查询-如果是机器人昵称，则按照中文gbk排序
        List<OrderItem> orderItemList = orderRevenueReportQuery.getOrderItemList();
        if(orderItemList != null && orderItemList.size() > 0){
            for (OrderItem orderItem :orderItemList){
                if("device_name".equals(orderItem.getColumn())){
                    orderItem.setColumn(" convert( " + orderItem.getColumn() + " using gbk) ");
                }
            }
        }

        //个人微信
        if(DeviceTypeEnum.DT_PC_WECHAT.getKey().equals(deviceType)){
            Page<DeviceWechatInfo> page = new Page<>();
            orderRevenueReportQuery.convert(page);
            DeviceWechatInfoQuery deviceWechatInfoQuery = new DeviceWechatInfoQuery();
            BeanUtils.copyProperties(orderRevenueReportQuery, deviceWechatInfoQuery);
            deviceWechatInfoQuery.setIdList(orderRevenueReportQuery.getDeviceUniqueIdList());
            deviceWechatInfoQuery.setMerId(merId);
            ArrayList<DeviceWechatInfo> deviceWechatInfoList =  deviceWechatInfoMapper.findByList(page, deviceWechatInfoQuery);
            BeanUtils.copyProperties(page, pageVo);
            if(deviceWechatInfoList != null && deviceWechatInfoList.size() > 0){
                for (DeviceWechatInfo deviceWechatInfo : deviceWechatInfoList){


                    OrderRevenueReportVo orderRevenueReportVo = new OrderRevenueReportVo();
                    orderRevenueReportVo.setDeviceUniqueId(deviceWechatInfo.getId());
                    orderRevenueReportVo.setDeviceName(deviceWechatInfo.getDeviceName());
                    orderRevenueReportVo.setDeviceRemark(deviceWechatInfo.getDeviceRemark());
                    orderRevenueReportVo.setHeadImgUrl(deviceWechatInfo.getHeadImgUrl());
                    orderRevenueReportVoList.add(orderRevenueReportVo);
                }
            }
        }else if(DeviceTypeEnum.DT_WORK_WECHAT.getKey().equals(deviceType)){
            Page<DeviceWxworkInfo> page = new Page<>();
            orderRevenueReportQuery.convert(page);
            DeviceWxworkInfoQuery deviceWxworkInfoQuery = new DeviceWxworkInfoQuery();
            BeanUtils.copyProperties(orderRevenueReportQuery, deviceWxworkInfoQuery);
            deviceWxworkInfoQuery.setIdList(orderRevenueReportQuery.getDeviceUniqueIdList());
            deviceWxworkInfoQuery.setMerId(merId);
            ArrayList<DeviceWxworkInfo> deviceWxworkInfoList =  deviceWxworkInfoMapper.findByList(page, deviceWxworkInfoQuery);
            BeanUtils.copyProperties(page, pageVo);
            if(deviceWxworkInfoList != null && deviceWxworkInfoList.size() > 0){
                for (DeviceWxworkInfo deviceWxworkInfo : deviceWxworkInfoList){
                    OrderRevenueReportVo orderRevenueReportVo = new OrderRevenueReportVo();
                    orderRevenueReportVo.setDeviceUniqueId(deviceWxworkInfo.getId());
                    orderRevenueReportVo.setDeviceName(deviceWxworkInfo.getDeviceName());
                    orderRevenueReportVo.setDeviceRemark(deviceWxworkInfo.getDeviceRemark());
                    orderRevenueReportVo.setHeadImgUrl(deviceWxworkInfo.getHeadImgUrl());
                    orderRevenueReportVoList.add(orderRevenueReportVo);
                }
            }
        }else if(DeviceTypeEnum.WX_PUB.getKey().equals(deviceType)){
            Page<WxpubInfoEntity> page = new Page<>();
            orderRevenueReportQuery.convert(page);
            WxpubInfoListQuery wxpubInfoListQuery = new WxpubInfoListQuery();
            BeanUtils.copyProperties(orderRevenueReportQuery, wxpubInfoListQuery);
            wxpubInfoListQuery.setIdList(orderRevenueReportQuery.getDeviceUniqueIdList());
            wxpubInfoListQuery.setMerId(merId);
            List<WxpubInfoEntity> wxpubInfoEntityList =  wxpubInfoMapper.queryList(page, wxpubInfoListQuery);
            BeanUtils.copyProperties(page, pageVo);
            if(wxpubInfoEntityList != null && wxpubInfoEntityList.size() > 0){
                for (WxpubInfoEntity wxpubInfoEntity : wxpubInfoEntityList){
                    OrderRevenueReportVo orderRevenueReportVo = new OrderRevenueReportVo();
                    orderRevenueReportVo.setDeviceUniqueId(wxpubInfoEntity.getId());
                    orderRevenueReportVo.setDeviceName(wxpubInfoEntity.getDeviceName());
                    orderRevenueReportVo.setDeviceRemark(wxpubInfoEntity.getDeviceRemark());
                    orderRevenueReportVo.setHeadImgUrl(wxpubInfoEntity.getHeadImgUrl());
                    orderRevenueReportVoList.add(orderRevenueReportVo);
                }
            }
        }

        //单个机器人查询总数
        long totalCount = pageVo.getTotal();
        if(totalCount == 0){
            throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "查询结果记录数为0");
        }

        String price = sysConfigMapper.selectByKey("export_record_price");

        //计算本次导出费用
        double amountTotal = 0.00D;
        if(amountTotal <= 10000){ //少于1万条，只收取1元
            amountTotal = 1.00D;
        }else{//总导出数大于1万条，则根据单价来计算，超过1万条的按照100条的单价费用来计算
            amountTotal = com.uzai.common.utils.Math.add(1.0D, ((totalCount - 10000)/100 + 1) * Double.parseDouble(price));
        }
        ExportAmountVo  exportAmountVo = new ExportAmountVo();
        exportAmountVo.setAmountTotal(amountTotal);
        exportAmountVo.setCountTotal(totalCount);
        exportAmountVo.setPrice(Double.parseDouble(price));

        return exportAmountVo;
    }
    
    /**
     * 订单收益统计结果导出数据
     * @author liuqi
     * @date 2021/8/13 11:38
     * @param orderRevenueReportExportResultDto
     * @return null
     */
    public void exportByQeuryResult(OrderRevenueReportExportResultDto orderRevenueReportExportResultDto){

        if(orderRevenueReportExportResultDto.getMerId() == null ){
            throw  new BusinessException(ResponseCode.BUSINESS_EXCEPTION, ResponseMsg.PARAM_ERROR);
        }

        if(org.apache.commons.lang3.StringUtils.isBlank(orderRevenueReportExportResultDto.getCode())){
            throw  new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "请输入验证码");
        }

        Merchant merchant = merchantMapper.selectById(orderRevenueReportExportResultDto.getMerId());
        if(merchant == null ){
            throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "运营商不存在");
        }

        //查询输入的验证码是否为系统默认密码
        if(!orderRevenueReportExportResultDto.getCode().equals(uzaiConsoleSysConfig.getDefaultPassword())){

            String val = (String) redisTemplate.opsForValue().get(String.format(CacheKey.ORDER_REVENUE_REPORT_EXPORT, orderRevenueReportExportResultDto.getMerId()));
            if (org.apache.commons.lang3.StringUtils.isNotBlank(val)){
                throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "30分钟只允许导出一次");
            }

            //获取存在redis中的验证码
            String codeByRedis = (String) redisTemplate.opsForValue().get(String.format(SmsType.SPECIAL_OPERATE.getDesc(), merchant.getMobile()));
            //判断验证码是否过期
            if (org.apache.commons.lang3.StringUtils.isBlank(codeByRedis)){
                throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, ResponseMsg.CODE_MISS);
            }

            //验证码是否正确
            if (!codeByRedis.equals(orderRevenueReportExportResultDto.getCode())){
                throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, ResponseMsg.CODE_ERR);
            }

            //验证成功了删除验证码
            redisTemplate.delete(String.format(SmsType.SPECIAL_OPERATE.getDesc(), merchant.getMobile()));
        }


        //页面查询条件
        OrderRevenueReportQuery orderRevenueReportQuery = orderRevenueReportExportResultDto.getOrderRevenueReportQuery();
        orderRevenueReportQuery.setMerId(orderRevenueReportExportResultDto.getMerId());

        //计算费用
        ExportAmountVo exportAmountVo = getExportAmount(orderRevenueReportQuery);

        //生成ZIP文件流
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        ZipOutputStream out = new ZipOutputStream(outputStream);

        //每个excel表格订单最大数为10000条
        int exportExcelMaxNum = Const.ExprotFile.EXPORT_EXCEL_MAX_NUM;
        //导出excel文件序号
        int exportFileNumber = 0;

        //存放导出文件对象(一万条一个表格)
        List<OrderRevenueReportExport> orderRevenueReportExportList = new ArrayList<>();
        //分页查询（每页10条）
        int page = 1;
        orderRevenueReportQuery.setCurrent(page); //只查第一页
        orderRevenueReportQuery.setSize(10); //每页查询10个
        Page<OrderRevenueReportVo> orderRevenueReportVoPage = orderRevenueReport(orderRevenueReportQuery);
        while (orderRevenueReportVoPage != null && orderRevenueReportVoPage.getRecords() != null && orderRevenueReportVoPage.getRecords().size() > 0) {
            for (OrderRevenueReportVo orderRevenueReportVo : orderRevenueReportVoPage.getRecords()) {
                OrderRevenueReportExport orderRevenueReportExport = new OrderRevenueReportExport();
                BeanUtils.copyProperties(orderRevenueReportVo, orderRevenueReportExport);
                orderRevenueReportExportList.add(orderRevenueReportExport);

                //判断条数，如果条数大于10000条，生成excel文件
                if(orderRevenueReportExportList.size() >= exportExcelMaxNum){
                    ByteArrayOutputStream byteArrayOutputStream = null;
                    try {
                        //导出的文件序号,每次导出+1
                        exportFileNumber ++ ;
                        String fileName = "订单收益报表_" + exportFileNumber +".xlsx";
                        //创建流
                        byteArrayOutputStream = new ByteArrayOutputStream();
                        //打包成ZIP文件
                        EasyExcel.write(byteArrayOutputStream, OrderRevenueReportExport.class).registerConverter(new LongStringConverter()).sheet("订单收益报表").doWrite(orderRevenueReportExportList);
                        ZipUtils.zip(out, new ByteArrayInputStream(byteArrayOutputStream.toByteArray()), fileName);
                        byteArrayOutputStream.close();
                        //清空本次导出的数据列表
                        orderRevenueReportExportList.clear();
                    }catch (Exception e){
                        if(byteArrayOutputStream != null){
                            try {
                                byteArrayOutputStream.close();
                            } catch (IOException ex) {
                                logger.error(ex.getMessage(), ex);
                            }
                        }
                        logger.error("----导出订单收益报表异常--error={}", e.getMessage());
                    }
                }

            }
            //循环查询下一页
            page ++;
            //最多支持导出100页数据
            if(page > 100){
                break;
            }
            orderRevenueReportQuery.setCurrent(page);
            orderRevenueReportVoPage = orderRevenueReport(orderRevenueReportQuery);
        }

        //最后将剩余不足10000条的记录，生成excel文件
        if(orderRevenueReportExportList.size() > 0){
            ByteArrayOutputStream byteArrayOutputStream = null;
            try {
                //导出的文件序号,每次导出+1
                exportFileNumber ++ ;
                String fileName = "订单收益报表_" + exportFileNumber +".xlsx";
                //创建流
                byteArrayOutputStream = new ByteArrayOutputStream();
                //打包成ZIP文件
                EasyExcel.write(byteArrayOutputStream, OrderRevenueReportExport.class).registerConverter(new LongStringConverter()).sheet("订单收益报表").doWrite(orderRevenueReportExportList);
                ZipUtils.zip(out, new ByteArrayInputStream(byteArrayOutputStream.toByteArray()), fileName);
                byteArrayOutputStream.close();
                //清空本次导出的数据列表
                orderRevenueReportExportList.clear();
            }catch (Exception e){
                if(byteArrayOutputStream != null){
                    try {
                        byteArrayOutputStream.close();
                    } catch (IOException ex) {
                        logger.error(ex.getMessage(), ex);
                    }
                }
                logger.error("----导出订单收益报表异常--error={}", e.getMessage());
            }
        }

        try {
            // 注意关闭流的顺序，在上传oss之前必须关闭流否则下载解压的时候会报“文件末端错误”的问题
            outputStream.close();
            out.close();
        }catch (Exception e){
            logger.error("----导出订单收益报表异常关闭流异常--error={}", e.getMessage());
        }finally {

        }

        //上传文件到OSS当中
        InputStream byteArrayInputStream = new ByteArrayInputStream(outputStream.toByteArray());
        String zipFileName = "订单收益报表_" + System.currentTimeMillis() + ".zip";
        //上传文件通讯录
        exportInfoService.uploadExportFile(byteArrayInputStream, orderRevenueReportExportResultDto.getMerId(), zipFileName, exportAmountVo, ExportInfoTypeEnum.EXPORT_INFO_ORDER_REVENUE_REPORT.getId());

        //往reids插入本次下载，允许30分钟下载一次，避免频繁提交
        redisTemplate.opsForValue().set(String.format(CacheKey.ORDER_REVENUE_REPORT_EXPORT, orderRevenueReportExportResultDto.getMerId()),orderRevenueReportExportResultDto.getMerId()+"",30, TimeUnit.MINUTES);


    }

}
